/*
 * Copyright 2007-2010 Jeremy Brown.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author <a href="http://jeremy-brown.com">Jeremy Brown</a>
 */

package groovy.prefuse.demos;

import java.io.*

import prefuse.data.*
import prefuse.data.io.*
import prefuse.util.io.*


/**
 * GraphReader instance that reads in tree-structured data in the
 * XML-based TreeML format. TreeML is an XML format originally created for
 * the 2003 InfoVis conference contest. A DTD (Document Type Definition) for
 * TreeML is
 * <a href="http://www.nomencurator.org/InfoVis2003/download/treeml.dtd">
 *  available online</a>.
 * 
 * @author <a href="http://jheer.org">jeffrey heer</a>
 */
public class SILDDPDomainTreeReader 
{
    /**
     * @see prefuse.data.io.GraphReader#readGraph(java.lang.String)
     */
    public Graph readGraph(String location) throws DataIOException
    {
        try {
            InputStream is = IOLib.streamFromString(location);
            if ( is == null )
                throw new DataIOException("Couldn't find " + location
                    + ". Not a valid file, URL, or resource locator.");
            return readGraph(is);
        } catch ( IOException e ) {
            throw new DataIOException(e);
        }   
    }
    
    
    /**
     * @see prefuse.data.io.AbstractTextTableReader#read(java.io.InputStream, prefuse.data.io.TableReadListener)
     */
    public Graph readGraph(InputStream is)
    	throws DataIOException
    {
        try 
        {
            Table m_nodes = null;
            Tree m_tree = null;
            Node m_activeNode = null;
            Node rootNode = null;
            int currentDepth = 0;
            
            m_tree = new Tree();
            m_nodes = m_tree.getNodeTable();
            m_nodes.addColumn("name", String.class); //holds the label for each node in the semantic domain
            
            //m_activeNode = m_tree.addRoot();
            
            String line;
            int lineno   = 0;
            
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            while ( (line=br.readLine()) != null ) {
                // increment the line number
                ++lineno;
                
                //read value of line
                if(line.matches("\\\\is.*"))
                {
                	//System.out.println("                    <- is");
                	//start of new node.

                	//determine depth of new node
                    // split on tab character
                	int thisDepth = -1; 
                	String domainIndex = "";
                    String[] cols = line.split(" ");
                    if(cols.length >= 2)
                    {
                    	thisDepth = 0;
                    	domainIndex = cols[1];
                    	for(int i=0; i<cols[1].length(); i++)
                    	{
                    		if(cols[1].charAt(i)=='.')
                    		{
                    			thisDepth++;
                    		}
                    	}
                    }

                    if(rootNode == null)
                    {
                    	rootNode = m_tree.addRoot();
                    	m_activeNode = rootNode;
                    }
                    else if(thisDepth == currentDepth)
                    {
                    	//add sibling m_activeNode
                        if(currentDepth > 0)
                        {
                        	m_activeNode = m_activeNode.getParent();
                        }
                        m_activeNode = m_tree.addChild(m_activeNode);
                    }
                    else if(thisDepth > currentDepth)
                    {
                    	//add child of m_activeNode
                    	currentDepth++;
                    	m_activeNode = m_tree.addChild(m_activeNode);
                    }
                    else if(thisDepth >= 0 && thisDepth < currentDepth)
                    {
                    	//end of parent node(s), end its branch
                    	for(; currentDepth > thisDepth; currentDepth--)
                    	{
                    		m_activeNode = m_activeNode.getParent();
                    	}
                    	
                    	//add sibling of m_activeNode
                    	m_activeNode = m_activeNode.getParent();
                        m_activeNode = m_tree.addChild(m_activeNode);
                    }
                	m_activeNode.set("name", domainIndex + " ");
                }
                else if(line.matches("\\\\sd.*"))
                {
                	//System.out.println("                    <- sd");
                	//new node's name
                	String val = "";
                    String[] cols = line.split(" ");
                    if(cols.length >= 2)
                    {
                    	val = cols[1];
                    	for(int i=2; i<cols.length; i++)
                    	{
                    		val = val + " " + cols[i];
                    	}
                    }
                    
                	//update name of current node
                	m_activeNode.set("name", m_activeNode.get("name") + val);

                	printLevel(currentDepth, val);
                }
                else if(line.matches("\\\\ex.*"))
                {
                	//System.out.println("                    <- ex");
                	//new example node
                	//add a new leaf

                	//new node's name
                	String val = "";
                    String[] cols = line.split(" ");
                    if(cols.length >= 2)
                    {
                    	val = cols[1];
                    	for(int i=2; i<cols.length; i++)
                    	{
                    		val = val + " " + cols[i];
                    	}
                    }
                    
                	//add child of m_activeNode
                    //don't change m_activeNode
                    Node leaf = m_tree.addChild(m_activeNode);

                    //update name of current node
                	leaf.set("name", val);
                	
                	printLevel(currentDepth, val);
                }
            }
            
            return m_tree;
        } catch ( Exception e ) {
            throw new DataIOException(e);
        }
    }
   
    public void printLevel(int depth, String name)
    {
    	for(int i=0; i<depth; i++)
    	{
    		//System.out.print(".");
    	}
    	//System.out.println(name);
    }
} // end of class SILDDPDomainTreeReader
